//
//  BMoya.swift
//  BMort_Swift
//
//  Created by anscen on 2022/7/19.
//

import UIKit
enum BMortState :String {
    case textfield  = "输入"
    case rate       = "利率"
    case subtitle   = "左右"
    case computer   = "计算"
}
public enum BDecimalState :String{
    case plus       = "A+B"
    case subtract   = "A-B"
    case multiply   = "AxB"
    case divide     = "A÷B"
    case power      = "A的B次方"
}
private let tip = "请输入真实有效的阿拉伯数字"
class BMoya{
    public var money = "贷款金额（元）"
    public var gjjmoney = "公积金贷款（元）"
    public var symoney = "商业贷款（元）"
    public var month = "贷款期数（月）"
    public var rate  = "贷款利率（%）"
    public var gjjrate  = "公积金利率（%）"
    public var syrate  = "商业利率（%）"
    public var discount  = "贷款折扣"
    public var totalmoney = "累计支付总金额(元)"
    public var totalrate  = "累计支付总利息(元)"
    public var computer = "计算"
    
    public func numeration(_ state :BDecimalState,_ one :String, _ two :String) ->String{
        if let _ = Float(one),let b = Float(two){
            let A = NSDecimalNumber(string: one)
            let B = NSDecimalNumber(string: two)
            switch state {
            case .plus:
                return A.adding(B).stringValue
            case .subtract:
                return A.subtracting(B).stringValue
            case .multiply:
                return A.multiplying(by: B).stringValue
            case .divide:
                if b == 0{
                    return "除数不能为0"
                }
                return A.dividing(by: B).stringValue
            case .power:
                guard let fore = Int(two) else { return tip }
                return A.raising(toPower:fore).stringValue
            }
        }
        return tip
    }
    func pointRange(money :String) ->String{
        if money.count == 0{
            return money
        }
        let stringValue :NSString = money as NSString
        let range = stringValue.range(of: ".")
        if range.location == NSNotFound{
            return "\(stringValue).00"
        }
        let dotIndex = range.location
        if stringValue.length == dotIndex + 2{
            return stringValue as String + "0"
        }
        if stringValue.length <= dotIndex + 3{
            return stringValue as String
        }
        let thirdstr = stringValue.substring(with: NSRange(location: dotIndex + 3, length: 1))
        let thirdstrInt = Int(thirdstr as String) ?? 0
        var  stringResult = stringValue.substring(to: dotIndex + 3)
        if thirdstrInt > 4{
            stringResult = numeration(.plus, stringResult, "0.01")
        }
        if stringResult.count == dotIndex + 2{
            return stringResult as String + "0"
        }
        if stringResult.count <= dotIndex + 2{
            return stringResult as String
        }
        return stringResult
    }
    //MARK:等额本息
    //@brief 每月月供额=〔贷款本金×月利率×(1＋月利率)＾还款月数〕÷〔(1＋月利率)＾还款月数-1〕
    func monthMoney(money :String,month :String,rate :String) ->String{
        let A = numeration(.divide, rate, "12")
        let rates = numeration(.divide, A, "100")
        let stringRate = numeration(.plus, "1", rates)
        let stringPowf = numeration(.power, stringRate, month)
        let stringA = numeration(.multiply,money, rates)
        let allMoney = numeration(.multiply, stringA, stringPowf)
        let del = numeration(.subtract, stringPowf, "1")
        let every = numeration(.divide, allMoney, del)
        return pointRange(money: every)
    }
    //@brier 每月应还利息=贷款本金×月利率×〔(1+月利率)^还款月数-(1+月利率)^(还款月序号-1)〕÷〔(1+月利率)^还款月数-1〕
    func rateMoney(money :String,month :String,rate :String,index :Int) ->String{
        let A = numeration(.divide, rate, "12")
        let rates = numeration(.divide, A, "100")
        let stringRate = numeration(.plus, "1", rates)
        let stringPowf = numeration(.power, stringRate, month)
        let del = numeration(.subtract, stringPowf, "1")
        let indexm = numeration(.subtract, "\(index)", "1")
        let stringPowfIndex = numeration(.power, stringRate, indexm)
        let stringC = numeration(.subtract, stringPowf, stringPowfIndex)
        let stringA = numeration(.multiply, money,rates)
        let stringB = numeration(.multiply, stringA,stringC)
        let moneys = numeration(.divide, stringB, del)
        return pointRange(money: moneys)
    }
    //brief 每月应还本金=贷款本金×月利率×(1+月利率)^(还款月序号-1)÷〔(1+月利率)^还款月数-1〕
    func capMonty(money :String,month :String,rate :String,index :Int) ->String{
        let stringA = monthMoney(money: money, month: month, rate: rate)
        let stringB = rateMoney(money: money, month: month, rate: rate, index: index)
        let every = numeration(.subtract, stringA, stringB)
        return pointRange(money: every)
    }
    //@brief 总利息=还款月数×每月月供额-贷款本金
    func totalRateMoney(money :String,month :String,rate :String) ->String{
        let stringA = totalMoney(money: money, month: month, rate: rate)
        let total = numeration(.subtract, stringA, money)
        return pointRange(money: total)
    }
    //累积还款总额 = 总利息 + 本金
    func totalMoney(money :String,month :String,rate :String) ->String{
        let stringA = monthMoney(money: money, month: month, rate: rate)
        let total = numeration(.multiply, stringA, month)
        return pointRange(money: total)
    }
    
    //MARK:等额本金
    //每月月供额=(贷款本金÷还款月数)+(贷款本金-已归还本金累计额)×月利率
    func everyMoneyRate(money :String,month :String,rate :String,index :Int) ->String{
        var therate = numeration(.divide, rate, "12")
        therate = numeration(.divide, therate, "100")
        let everymoney = numeration(.divide, money, month)
        let already = numeration(.multiply, "\(index)", everymoney)
        let stringb = numeration(.subtract,money, already)
        let stringc = numeration(.multiply, therate, stringb)
        let everyMonthPay = numeration(.plus, everymoney, stringc)
        return pointRange(money: everyMonthPay)
    }
    //每月应还本金=贷款本金÷还款月数
    func everymoney(money :String, month :String) ->String{
        let mon = numeration(.divide, money,month)
        return pointRange(money: mon)
    }
    //每月应还利息
    func everyrate(money :String,month :String,rate :String,index :Int)->String{
        let everyMonthRate = everyMoneyRate(money: money, month: month, rate: rate, index: index)
        let everyMonthMoney = everymoney(money: money, month: month)
        let everyRate = numeration(.subtract, everyMonthRate, everyMonthMoney)
        return pointRange(money: everyRate)
    }
    //总利息=〔(总贷款额÷还款月数+总贷款额×月利率)+总贷款额÷还款月数×(1+月利率)〕÷2×还款月数-总贷款额
    func totalrate(money :String,month :String,rate :String) ->String{
        var theRate = numeration(.divide, rate, "12")
        theRate = numeration(.divide, theRate, "100")
        let stringA = numeration(.multiply, money, rate)
        let everyMoney = numeration(.divide, money, month)
        let stringB = numeration(.plus, stringA, everyMoney)
        let stringRate = numeration(.plus, "1", theRate)
        let stringC = numeration(.multiply, everyMoney, stringRate)
        let stringAll = numeration(.plus,stringB, stringC)
        var stringE = numeration(.divide, stringAll, "2")
        stringE = numeration(.subtract, stringE, money)
        return pointRange(money: stringE)
    }
    //累积还款总额 = 总利息 + 本金
    func totalmoney(money :String,month :String,rate :String)->String{
        let stringRate = totalrate(money: money, month: month, rate: rate)
        let stringAll = numeration(.plus, stringRate, money)
        return pointRange(money: stringAll)
    }
}
